package info.hexin.mvc.config;

import info.hexin.ioc.IocBean;
import info.hexin.ioc.context.Ioc;
import info.hexin.lang.Strings;
import info.hexin.log.Log;
import info.hexin.log.Logs;
import info.hexin.mvc.annotation.HeaderParam;
import info.hexin.mvc.annotation.MultiFile;
import info.hexin.mvc.annotation.Param;
import info.hexin.mvc.annotation.Path;
import info.hexin.mvc.annotation.PathParam;
import info.hexin.mvc.annotation.View;
import info.hexin.mvc.methodtree.Arg;
import info.hexin.mvc.methodtree.MethodInfo;
import info.hexin.mvc.methodtree.ViewInfo;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class Loading {
    private static final Log log = Logs.get();

    public static void scanWebAction(Ioc ioc, Collection<String> collectionMaping) throws InstantiationException,
            IllegalAccessException {

        for (String mapping : collectionMaping) {

            String prefix = "";
            // 保证filter 默认是从根开始的
            if (mapping.startsWith("/*") || mapping.startsWith("*.")) {
                log.info("filter is not prefix");
            } else {
                int prefixIndex = mapping.indexOf("*");
                prefix = mapping.substring(0, prefixIndex);
            }
            log.debug("filter mapping >>>>> {} , prefix >>>>> {}", mapping, prefix);

            // 需要将context 存放到缓存中保存起来
            Map<String, IocBean> map = ioc.getIocBeans();
            for (Map.Entry<String, IocBean> entry : map.entrySet()) {
                IocBean iocBean = entry.getValue();
                loadMethod(iocBean, prefix);
            }
        }
    }

    private static void loadMethod(IocBean iocBean, String prefix) throws InstantiationException, IllegalAccessException {
        Class<?> clazz = iocBean.getClazz();
        Path path = clazz.getAnnotation(Path.class);
        String tempClassPathValue = "";

        // 类上没有标注注解
        if (path != null) {
            tempClassPathValue = path.value();
            if (Strings.isNotBlank(tempClassPathValue)) {
                tempClassPathValue = tempClassPathValue + "/";
            } else {
                // 继承 父类
                // Class<?> superClass = clazz.getSuperclass();
                tempClassPathValue = "";
            }
        }

        String classPathValue = tempClassPathValue;
        if (Strings.isNotBlank(prefix)) {
            classPathValue = prefix + tempClassPathValue;
        }
        if (log.isDebugEnabled()) {
            log.debug("class Name ClassPathValue >>>> " + tempClassPathValue + " ; add filter mapping >>>> "
                    + classPathValue);
        }
        Method[] methods = clazz.getMethods();
        for (Method method2 : methods) {

            Path methodPath = method2.getAnnotation(Path.class);
            if (methodPath != null) {

                if (log.isDebugEnabled()) {
                    log.debug(" MethodName : " + method2.getName() + "");
                }
                MethodInfo methodInfo = new MethodInfo();
                methodInfo.setIocBean(iocBean);
                methodInfo.setReflectMethod(method2);
                String methodPathValue = methodPath.value();

                // 已经为classAtValue 增加了 "\"
                String fullUrl = classPathValue + methodPathValue;
                // ? ?
                // hexin/{name}/add/{id}
                Map<String, Integer> pathParmIndex = new HashMap<String, Integer>();
                if (fullUrl.contains("{")) {
                    String tmpFullUrl = null;
                    if (fullUrl.startsWith("/")) {
                        tmpFullUrl = fullUrl.substring(1);
                    } else {
                        tmpFullUrl = fullUrl;
                    }
                    String[] urls = tmpFullUrl.split("/");
                    for (int i = 0; i < urls.length; i++) {
                        String tempUrl = urls[i];
                        if (tempUrl.contains("{")) {
                            pathParmIndex.put(tempUrl.substring(1, tempUrl.length() - 1), i);
                        }
                    }
                }

                methodInfo.setUrl(fullUrl);
                methodInfo.setMethod(methodPath.method());
                info.hexin.mvc.annotation.Method methodMethod = methodPath.method();
                log.info("methodPathValue >>>> " + methodPathValue + " ;full path >>>> " + methodInfo.getUrl()
                        + " ;method >>> " + methodMethod);

                // 方法的参数列表
                Class<?>[] paramClass = method2.getParameterTypes();
                Annotation[][] paramAnnotation = method2.getParameterAnnotations();
                for (int i = 0; i < paramClass.length; i++) {
                    Arg arg = new Arg();
                    arg.setParamClass(paramClass[i]);

                    // / method param annotation
                    Annotation[] annotations = paramAnnotation[i];
                    if (annotations.length == 1) {
                        // 写在这里 能将部分计算转移到启动时候
                        Class<?> anClass = annotations[0].annotationType();
                        log.debug("  anClass >>> " + anClass);// 参数类型
                        arg.setAnClass(anClass);
                        Annotation annotation = annotations[0];
                        if (anClass == HeaderParam.class) {
                            HeaderParam headerParam = (HeaderParam) annotation;
                            arg.setName(headerParam.value());
                        } else if (anClass == Param.class) {
                            Param param = (Param) annotation;
                            arg.setName(param.value());
                        } else if (anClass == PathParam.class) {
                            try {
                                PathParam pathParam = (PathParam) annotation;
                                String pathParamName = pathParam.value();
                                arg.setPathIndex(pathParmIndex.get(pathParamName));
                            } catch (Exception e) {
                                throw new RuntimeException("method >>>> " + method2.getName()
                                        + " @Path is not {} wildcard character!");
                            }
                        } else if (anClass == MultiFile.class) {
                            MultiFile multiFile = (MultiFile) annotation;
                            String multiFileName = multiFile.value();
                            arg.setName(multiFileName);
                        }
                    }
                    methodInfo.addArg(arg);
                }

                View view = method2.getAnnotation(View.class);
                ViewInfo viewInfo = new ViewInfo();
                if (view != null) {
                    viewInfo.setViewType(view.type());
                    methodInfo.setViewInfo(viewInfo);
                }
                // add to urlmaping
                UrlMaping.addMethodInfo(methodInfo);
            }
        }
    }
}
